#include "vl_valid.h"

using namespace VL;

/**
 * +======================================================================================================================+
 * @Author: CimZzz
 * @Date: 2022-08-11 17:25:20
 * 
 * 代码分割块，以下内容涉及: 
 * 
 * BaseValidItem
 * 
 */

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 23:54:28
 * 
 * 构造函数
 * 
 * @param code 校验码
 */
BaseValidItem::BaseValidItem(uint32_t code, const std::string& key): code(code), key(key) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 23:55:03
 * 
 * 获取校验码
 * 
 * @return 返回校验码
 */
uint8_t BaseValidItem::getCode() const {
	return this->code;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 08:23:44
 * 
 * 获取节点 Key 值
 * 
 * @return 返回节点 Key 值
 */
const std::string& BaseValidItem::getKey() const {
	return this->key;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 17:12:57
 * 
 * 添加子校验项并返回其指针
 * 
 * @param childItem 子校验项指针
 * 
 * @return 子校验项指针
 */
BaseValidItem* BaseValidItem::addChildItem(BaseValidItem* childItem) {
	if(this->childList.get() == nullptr) {
		this->childList = std::shared_ptr<std::vector<std::shared_ptr<BaseValidItem>>>(new std::vector<std::shared_ptr<BaseValidItem>>);
	}

	childItem->parent = this;
	this->childList->push_back(std::shared_ptr<BaseValidItem>(childItem));
	return childItem;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:10:45
 * 
 * 添加兄弟校验项, 并返回其指针
 * 
 * @param childItem 兄弟校验项指针
 * 
 * @return 兄弟校验项指针
 * 
 * @note 如果当前校验项是顶层, 则无动作并返回自身指针
 */
BaseValidItem* BaseValidItem::addBrother(BaseValidItem* childItem) {
	if(this->parent == nullptr) {
		if(childItem != nullptr) {
			delete childItem;
		}
		return this;
	}

	if(childItem == nullptr) {
		return this;
	}

	return this->parent->addChildItem(childItem);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 23:58:45
 * 
 * 校验方法
 * 
 * @param prop 属性指针
 * @param data 数据指针
 * 
 * @return 如果校验成功返回 true
 */
bool BaseValidItem::valid(const std::shared_ptr<VLProp>& prop, void* data) {
	return 0;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:26:06
 * 
 * 写入方法
 * 
 * @param mapProp 父级 Map 指针
 * @param data 数据指针
 */
void BaseValidItem::write(MapProp* mapProp, void* data) {

}

/**
 * +======================================================================================================================+
 * @Author: CimZzz
 * @Date: 2022-08-11 17:30:14
 * 
 * 代码分割块，以下内容涉及: 
 * 
 * ValidStream
 * 
 */

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 00:00:28
 * 
 * 构造方法
 */
ValidStream::ValidStream() {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 07:59:41
 * 
 * 添加验证项
 * 
 * @param validItem 验证项指针
 * 
 * @return 验证项指针
 */
BaseValidItem* ValidStream::addValidItem(BaseValidItem* validItem) {
	this->validList.push_back(std::shared_ptr<BaseValidItem>(validItem));
	return validItem;
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:04:46
 * 
 * 校验当前全部校验选项
 * 
 * @param validStream 校验文件
 * @param paramList 参数列表
 * 
 * @return 校验成功返回 0, 校验未知失败返回 1, 其余自定义
 */
uint32_t ValidStream::valid(ValidFile* validFile, const std::vector<void*>& paramList) {
	if(validFile == nullptr) {
		return 1;
	}
	if(!validFile->load()) {
		return 1;
	}

	MapProp* validProp = (MapProp*) validFile->validProp.get();
	uint32_t validCode = 0;
	uint16_t begin = 0;

	for(auto iter = this->validList.begin() ; iter != this->validList.end() ; iter ++) {
		auto validItem = (*iter);
		validCode = this->validItem(validProp->get(validItem->getKey()), validItem, begin, paramList);
		if(validCode != 0) {
			break;
		}
	}

	return validCode;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 17:15:08
 * 
 * 校验当前时间戳选项
 * 
 * @param validStream 校验文件
 * @param paramList 参数列表
 * 
 * @return 校验成功返回 0, 校验未知失败返回 1, 其余自定义
 */
uint32_t ValidStream::valid(std::shared_ptr<ValidFile>& validFile, const std::vector<void*>& paramList) {
	return this->valid(validFile.get(), paramList);
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-11 18:31:00
 * 
 * 校验指定校验选项
 * 
 * @param prop 属性指针
 * @param validItem 校验项指针
 * @param begin 参数起始下标
 * @param paramList 参数列表
 * 
 * @return 校验成功返回 0, 校验未知失败返回 1, 其余自定义
 */
uint32_t ValidStream::validItem(const std::shared_ptr<VLProp>& prop,  const std::shared_ptr<BaseValidItem>& validItem, uint16_t& begin, const std::vector<void*>& paramList) {
	uint32_t validCode = 0;
	if(validItem->childList.get() == nullptr) {
		if(begin >= paramList.size()) {
			validCode = validItem->getCode();
		}
		else if(!validItem->valid(prop, paramList.at(begin ++))) {
			validCode = validItem->getCode();
		}
	} else {
		if(prop->isMap()) {
			auto map = (MapProp *) prop.get();
			for(auto iter = validItem->childList->begin() ; iter != validItem->childList->end() ; iter ++) {
				auto childItem = (*iter);
				validCode = this->validItem(map->get(childItem->getKey()), childItem, begin, paramList);
				if(validCode != 0) {
					break;
				}
			}
		} else {
			validCode = validItem->getCode();
		}
	}

	return validCode;
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:27:57
 * 
 * 写入当前全部校验选项
 * 
 * @param validStream 校验文件
 * @param paramList 参数列表
 */
void ValidStream::write(ValidFile* validFile, const std::vector<void*>& paramList) {
	if(validFile == nullptr) {
		return;
	}
	validFile->validProp.reset(new RootProp);

	MapProp* validProp = (MapProp*) validFile->validProp.get();
	
	this->writeProp(validProp, paramList);

	validFile->override();
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:27:57
 * 
 * 写入当前全部校验选项
 * 
 * @param validStream 校验文件
 * @param paramList 参数列表
 */
void ValidStream::write(std::shared_ptr<ValidFile>& validFile, const std::vector<void*>& paramList) {
	this->write(validFile.get(), paramList);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:33:47
 * 
 * 写入指定校验选项
 * 
 * @param prop 父级 Map 属性指针
 * @param validItem 校验项指针
 * @param begin 参数起始下标
 * @param paramList 参数列表
 */
void ValidStream::writeItem(MapProp* prop, const std::shared_ptr<BaseValidItem>& validItem, uint16_t& begin, const std::vector<void*>& paramList) {
	if(validItem->childList.get() == nullptr) {
		if(begin >= paramList.size()) {
			return;
		}
		validItem->write(prop, paramList.at(begin ++));
	} else {
		std::shared_ptr<VLProp> childMapProp(new MapProp);
		MapProp* childMap = (MapProp *) childMapProp.get();
		prop->push(validItem->getKey(), childMapProp);
		for(auto iter = validItem->childList->begin() ; iter != validItem->childList->end() && begin < paramList.size() ; iter ++) {
			auto childItem = (*iter);
			this->writeItem(childMap, childItem, begin, paramList);
		}
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-13 13:15:54
 * 
 * 将当前校验项写入属性表中
 * 
 * @param mapProp 属性表指针
 * @param paramList 参数列表
 */
void ValidStream::writeProp(MapProp* mapProp, const std::vector<void*>& paramList) {
	uint16_t begin = 0;

	for(auto iter = this->validList.begin() ; iter != this->validList.end() && begin < paramList.size() ; iter ++) {
		auto validItem = (*iter);
		this->writeItem(mapProp, validItem, begin, paramList);
	}
}

/**
 * +======================================================================================================================+
 * @Author: CimZzz
 * @Date: 2022-08-11 18:52:47
 * 
 * 代码分割块，以下内容涉及: 
 * 
 * ValidFile
 * 
 */

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 15:56:09
 * 
 * 构造函数
 */
ValidFile::ValidFile(): validFile(nullptr) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-19 19:19:39
 * 
 * 构造函数
 * 
 * @param validFile 校验文件
 */
ValidFile::ValidFile(const VLFile& validFile): validFile(new VLFile(validFile)) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-19 19:19:57
 * 
 * 构造函数
 * 
 * @param validFile 校验文件指针
 */
ValidFile::ValidFile(VLFile* validFilePtr): validFile(validFilePtr) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-19 19:20:12
 * 
 * 构造函数
 * 
 * @param validFilePtr 校验文件指针
 */
ValidFile::ValidFile(const std::shared_ptr<VLFile>& validFilePtr): validFile(validFilePtr) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 16:02:27
 * 
 * 安装校验原始文件
 * 
 * @param validFile 校验原始文件
 */
void ValidFile::setupFile(const VLFile& validFile) {
	std::shared_ptr<VLFile> filePtr(new VLFile(validFile));
	this->setupFile(filePtr);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 15:58:57
 * 
 * 安装校验原始文件
 * 
 * @param validFilePtr 校验原始文件指针
 */
void ValidFile::setupFile(VLFile* validFilePtr) {
	std::shared_ptr<VLFile> filePtr(validFilePtr);
	this->setupFile(filePtr);
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 16:00:18
 * 
 * 安装校验原始文件
 * 
 * @param validFilePtr 校验原始文件指针
 */
void ValidFile::setupFile(const std::shared_ptr<VLFile>& validFilePtr) {
	this->validFile = validFilePtr;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 16:30:00
 * 
 * 初始化校验属性
 * 
 * @param isForceReload 是否强制重新加载校验属性
 * 
 * @return 读取成功返回 true
 */
bool ValidFile::load(bool isForceReload) {
	if(this->validFile.get() == nullptr) {
		return false;
	}

	if(this->validProp.get() != nullptr && !isForceReload) {
		return true;
	}

	std::shared_ptr<RootProp> rootProp(new RootProp);
	auto file = *this->validFile;

	if(!rootProp->readFromVLCFile(file)) {
		return false;
	}

	this->validProp = rootProp;
	return true;
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-11 19:40:02
 * 
 * 写入校验属性
 */
void ValidFile::override() {
	if(this->validFile.get() == nullptr || this->validProp.get() == nullptr) {
		return;
	}
	auto file = *this->validFile;
	if(file.makeSureParentDirExist()) {
		this->validProp->writeToVLCFile(file);
	}
}


/**
 * @Author: CimZzz
 * @Date: 2022-08-12 14:51:54
 * 
 * 获取校验原始文件
 */
const std::shared_ptr<VLFile>& ValidFile::getValidFile() const {
	return this->validFile;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-10 16:27:06
 * 
 * 获取校验属性
 * 
 * @return 校验属性指针
 */
const std::shared_ptr<RootProp>& ValidFile::getValidProp() const {
	return this->validProp;
}